(post
 :title "Curried functions and the beauty of scheme's cut"
 :date (make-date* 2016 9 26)
 :tags '("guile" "scheme" "curry" "curried" "haskell" "cut")

 (h3 [Curried functions in Haskell])
 (p [
     If you weren't aware, functions in languages like ML and Haskell are
     curried, meaning each function technically only accepts
     one parameter.
     Mathematically, curried functions help programmers reason
     about runtimes since each function only has one parameter.
     Programatically, however, their use is not immediately apparent. Both
     Haskell and ML allow the programmer to declare functions with multiple
     parameters, which are then curried under the hood. Now I'm sure
     experienced Haskellers are shaking their head, and could explain all the
     programmatic features currying provides, but for my inexperienced self,
     I enjoyed the ease in building partially ordered functions.
     ])


 (h3 [Example])
 (p [
     To make this clear let's look at common map subroutine, where we
        increment each element in a list, in lisp and
     haskell. Since (+ 1) in lisp returns 1, we have to nest this
     procedure in a lambda specifying + will take two arguments:
     ])

 (code-block-scheme
  (car
   [(map (lambda (x) (+ 1 x))
         '(1 2 3))]))

 (p [
     In haskell, however, (+ 1) returns an increment function of one
     argument, exactly what the lisp boilerplate does. It looks like:
     ])
 
 (code-block-scheme
  (car
   [(map (+ 1) '(1 2 3))]))

 (p [
     There are some limitations when using curried functions in this manner.
     In particular, commutivity is required: (+ 1 _) works but (- _ 1) does not.
     ])


 (h3 [Lisp's cut])
 (p [
     Eventually I found about cut, an awesome lisp macro that implements
     the nice feature currying provides, without the limitations. Cut
     essentially allows the programmer to specify which procedure arguments
     will be supplied later, and returns a new procedure with those rules.
     So for the above example, we would use cut like this:
     ])

 (code-block-scheme
  (car
   [(map (cut + 1 <>) '(1 2 3))]))
 (p [
     As you may have noted, <> can be anywhere, which means that we can deal
     with non-communitive operators: (cut - <> 1), multiple arugments:
     (cut - <> <>), an arbitrary number of arugments: (cut - <...>) even
     the procedure itself: (cut <> 1 1)
     ]))
